#include "HiK_opencv.h"
#include <iostream>

#include <mutex>
//全局变量
size_t img_count[CAM_NUM] = {0, 0};
std::mutex pubimage_mutex[CAM_NUM];          //用于多线程图像采集与储存
std::vector<cv::Mat> image_squence[CAM_NUM]; //储存采集图像
LONG g_nPort;
LONG g_nPort_set[CAM_NUM];
cv::Mat g_BGRImage[CAM_NUM];
/**
 * 回调函数用于开辟新线程进行数据的采集
 */
void CALLBACK HK_camera::DecCBFun(int nPort, char *pBuf, int nSize, FRAME_INFO *pFrameInfo, void *nUser, int nReserved2)
{
  if (pFrameInfo->nType == T_YV12)
  {
#ifdef DEBUG
    std::cout << "the frame infomation is T_YV12" << std::endl;
#endif
    if (g_BGRImage[0].empty())
    {
      g_BGRImage[0].create(pFrameInfo->nHeight, pFrameInfo->nWidth, CV_8UC3);
    }
    if (g_BGRImage[1].empty())
    {
      g_BGRImage[1].create(pFrameInfo->nHeight, pFrameInfo->nWidth, CV_8UC3);
    }
    cv::Mat YUVImage(pFrameInfo->nHeight + pFrameInfo->nHeight / 2, pFrameInfo->nWidth, CV_8UC1, (unsigned char *)pBuf);
#ifdef DEBUG
    printf("The nport is---------- =%ld \n", nPort);
#endif
    switch (nPort)
    {
    case 0:
      pubimage_mutex[0].lock();
      cvtColor(YUVImage, g_BGRImage[0], COLOR_YUV2BGR_YV12);
      image_squence[0].push_back(g_BGRImage[0]);
      pubimage_mutex[0].unlock();
      break;

    case 1:
      pubimage_mutex[1].lock();
      cvtColor(YUVImage, g_BGRImage[1], COLOR_YUV2BGR_YV12);
      image_squence[1].push_back(g_BGRImage[1]);
      pubimage_mutex[1].unlock();
      break;

    default:
      break;
    }

    //imshow("RGBImage", g_BGRImage);
    //waitKey(15);

    YUVImage.~Mat();
  }
}

void CALLBACK HK_camera::g_RealDataCallBack_V30(LONG lPlayHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, void *pUser)
{
  DWORD dRet;
  DWORD CameraIndex = 0;

  CameraIndex = lPlayHandle;
#ifdef DEBUG
  printf("The lPlayHandle =%ld \n", CameraIndex);
#endif
  if (dwDataType == NET_DVR_STREAMDATA)
  {
    if (dwBufSize > 0 && g_nPort_set[CameraIndex] != -1)
    {
      if (!PlayM4_InputData(g_nPort_set[CameraIndex], pBuffer, dwBufSize))
      {
        std::cout << "fail input data" << std::endl;
      }
      else
      {
#ifdef DEBUG
        std::cout << "success input data" << std::endl;
#endif
      }
    }
  }
}

HK_camera::~HK_camera(void)
{
}

bool HK_camera::Init()
{
  if (NET_DVR_Init())
  {
    return true;
  }
  else
  {
    return false;
  }
}

bool HK_camera::Login(char *sDeviceAddress, char *sUserName, char *sPassword, WORD wPort)
{
  NET_DVR_USER_LOGIN_INFO pLoginInfo = {0};
  NET_DVR_DEVICEINFO_V40 lpDeviceInfo = {0};

  pLoginInfo.bUseAsynLogin = 0; //同步登录方式
  strcpy(pLoginInfo.sDeviceAddress, sDeviceAddress);
  strcpy(pLoginInfo.sUserName, sUserName);
  strcpy(pLoginInfo.sPassword, sPassword);
  pLoginInfo.wPort = wPort;

  lUserID = NET_DVR_Login_V40(&pLoginInfo, &lpDeviceInfo);
  camera_index = lUserID;

  if (lUserID < 0)
  {
    return false;
  }
  else
  {
    return true;
  }
}

void HK_camera::show()
{
  if (PlayM4_GetPort(&g_nPort_set[camera_index])) //获取播放库通道号
  {
    if (PlayM4_SetStreamOpenMode(g_nPort_set[camera_index], STREAME_REALTIME)) //设置流模式
    {
      if (PlayM4_OpenStream(g_nPort_set[camera_index], NULL, 0, 1024 * 1024)) //打开流
      {
        if (PlayM4_SetDecCallBackExMend(g_nPort_set[camera_index], DecCBFun, NULL, 0, NULL))
        {
          if (PlayM4_Play(g_nPort_set[camera_index], NULL))
          {
            std::cout << "success to set play mode" << std::endl;
          }
          else
          {
            std::cout << "fail to set play mode" << std::endl;
          }
        }
        else
        {
          std::cout << "fail to set dec callback " << std::endl;
        }
      }
      else
      {
        std::cout << "fail to open stream" << std::endl;
      }
    }
    else
    {
      std::cout << "fail to set stream open mode" << std::endl;
    }
  }
  else
  {
    std::cout << "fail to get port" << std::endl;
  }

  NET_DVR_PREVIEWINFO struPlayInfo = {0};
  struPlayInfo.hPlayWnd = NULL;
  struPlayInfo.lChannel = 1;
  struPlayInfo.dwStreamType = 0;
  struPlayInfo.dwLinkMode = 0;
  struPlayInfo.bBlocked = 1;

  if (NET_DVR_RealPlay_V40(lUserID, &struPlayInfo, g_RealDataCallBack_V30, NULL))
  {
    // namedWindow("RGBImage");
    std::cout << "test t here" << std::endl;
  }
}

void HK_camera::publish()
{
  pubimage_mutex[camera_index].lock();

  if (image_squence[camera_index].size() > 0)
  {
#ifndef DEBUG
    cout << "The count of this image from camera \t" << camera_index << "\t is  \t" << img_count[camera_index]++ << endl;
#endif
  cv:
    Mat Tmp_Image = (image_squence[camera_index]).front();
    std::vector<cv::Mat>::iterator k = (image_squence[camera_index]).begin();
    image_squence[camera_index].erase(k);
    ros::Time time_c = ros::Time::now();
    sensor_msgs::ImagePtr img_msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", Tmp_Image).toImageMsg();
    img_msg->header.stamp = time_c;
    pub_ptr->publish(img_msg);
  }

  pubimage_mutex[camera_index].unlock();
}